﻿using System.Linq;
using Notoric.Commanding.CommandBase;

namespace Notoric.ViewModel
{
    /// <summary>
    /// An undoable command for adding a new lyricist to a composition metadata.
    /// </summary>
    public class AddLyricistCommand : UndoableCommandBase
    {
        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="AddLyricistCommand"/> class.
        /// </summary>
        /// <param name="undoStack">The undo command stack</param>
        /// <param name="redoStack">The redo command stack</param>
        public AddLyricistCommand(CommandStack undoStack, CommandStack redoStack)
            : base(undoStack, redoStack)
        {
            AddParameter<Elements.Composition>("Composition", ParameterDirection.In);
            AddParameter<Elements.Person>("CreatedLyricist", ParameterDirection.Out);

            Name = "Add Lyricist";
        }

        #endregion

        #region Command Logic

        /// <inheritdoc/>
        protected override void CommandOperation(object parameter)
        {
            var modelComposition = Composition.AdaptedElement as Model.Elements.CompositionElement;
            var modelPerson = new Model.Elements.PersonElement(Composition.AdaptedPart, modelComposition);
            modelComposition.Lyricists.Add(modelPerson);
            CreatedLyricist = Composition.Lyricists.First(c => c.AdaptedElement == modelPerson);

            Composition.FindOwner<Elements.Project>().IsModified = true;
        }

        /// <inheritdoc/>
        protected override void RedoOperation()
        {
            var modelComposition = Composition.AdaptedElement as Model.Elements.CompositionElement;
            var modelPerson = CreatedLyricist.AdaptedElement as Model.Elements.PersonElement;
            modelComposition.Lyricists.Add(modelPerson);
            var vmLyricist = Composition.Lyricists.First(c => c.AdaptedElement == CreatedLyricist.AdaptedElement);
            Composition.Lyricists[Composition.Lyricists.IndexOf(vmLyricist)] = CreatedLyricist;

            Composition.FindOwner<Elements.Project>().IsModified = true;
        }

        /// <inheritdoc/>
        protected override void UndoOperation()
        {
            var modelComposition = Composition.AdaptedElement as Model.Elements.CompositionElement;
            var modelPerson = CreatedLyricist.AdaptedElement as Model.Elements.PersonElement;
            modelComposition.Lyricists.Remove(modelPerson);

            Composition.FindOwner<Elements.Project>().IsModified = true;
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets or sets the composition to which the lyricist is added.
        /// </summary>
        /// <value>
        /// <para>
        /// Type: <see cref="Elements.Composition"/>
        /// </para>
        /// <para>
        /// The composition to which the lyricist is added.<br/>
        /// This property wraps the "Composition" command parameter.
        /// </para>
        /// </value>
        public Elements.Composition Composition
        {
            get { return GetParameterValue<Elements.Composition>("Composition"); }
            set { SetParameterValue<Elements.Composition>("Composition", value); }
        }

        /// <summary>
        /// Gets or sets the created lyricist.
        /// </summary>
        /// <value>
        /// <para>
        /// Type: <see cref="Elements.Person"/>
        /// </para>
        /// <para>
        /// The lyricist created by this command.<br/>
        /// This property wraps the "CreatedLyricist" command parameter.
        /// </para>
        /// </value>
        public Elements.Person CreatedLyricist
        {
            get { return GetParameterValue<Elements.Person>("CreatedLyricist"); }
            private set { SetParameterValue<Elements.Person>("CreatedLyricist", value); }
        }

        #endregion
    }
}
